package com.kun.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.kun.common.file.minio.MinioTemplate;
import com.kun.dto.SysFileDTO;
import com.kun.dto.SysFileDelMoveDTO;
import com.kun.entity.SysFile;
import com.kun.entity.SysFileStorage;
import com.kun.service.FileStorageService;
import com.kun.service.SysFileService;
import com.kun.util.ResponseResult;
import io.minio.ObjectWriteResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 * 文件管理
 *
 * @author kun.li
 */
@RestController
@RequestMapping("fileManager")
@RequiredArgsConstructor
@Tag(name = "文件管理")
@Slf4j
public class FileManagerController {

    private final FileStorageService fileStorageService;

    private final SysFileService sysFileService;

    @Autowired
    private MinioTemplate minioTemplate;

    @GetMapping("fileStorageTree")
    @Operation(summary = "获取文件目录树")
    public ResponseResult<List<Tree<String>>> fileStorageTree() {
        return ResponseResult.success(fileStorageService.getFileStorageTree());
    }

    @Operation(summary = "保存文件目录树")
    @PostMapping("saveFileStorageTree")
    public ResponseResult<Boolean> saveFileStorageTree(@RequestBody SysFileStorage fileStorage) throws Exception {
        // 保存文件目录树时 创建存储路径
        String storageParentId = fileStorage.getStorageParentId();
        SysFileStorage sysFileStorage = fileStorageService.getById(storageParentId);
        String storageAbsoluteDirectory = sysFileStorage.getStorageAbsoluteDirectory();
        String storageDirectory = null;
        if (StrUtil.isEmpty(storageAbsoluteDirectory)) {
            storageDirectory = fileStorage.getStorageDirectory();
        } else {
            storageDirectory = storageAbsoluteDirectory + fileStorage.getStorageDirectory();
        }
        ObjectWriteResponse bucketFolder = minioTemplate.createBucketFolder(storageDirectory);
        fileStorage.setStorageAbsoluteDirectory(bucketFolder.object());
        return ResponseResult.success(fileStorageService.save(fileStorage));
    }

    @Operation(summary = "修改文件目录树")
    @PostMapping("updateFileStorageTree")
    public ResponseResult<Boolean> updateFileStorageTree(@RequestBody SysFileStorage fileStorage) {
        return ResponseResult.success(fileStorageService.updateById(fileStorage));
    }


    @Operation(summary = "删除文件目录树")
    @DeleteMapping("updateFileStorageTree/{storageId}")
    public ResponseResult<Boolean> removeFileStorageTree(@PathVariable String storageId) {
        // 删除文件目录时 先判断目录下是否有子目录,如果有 不让删除
        LambdaQueryWrapper<SysFileStorage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysFileStorage::getStorageParentId, storageId);
        List<SysFileStorage> fileStorages = fileStorageService.list(queryWrapper);
        if (CollUtil.isNotEmpty(fileStorages)) {
            return ResponseResult.failed("目录下有子目录,不允许删除");
        }
        long count = sysFileService.count(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getStorageId, storageId));
        if (count > 0) {
            return ResponseResult.failed("目录下有文件,不允许删除");
        }
        fileStorageService.removeById(storageId);
        return ResponseResult.success(Boolean.TRUE);
    }


    @GetMapping("fileList/{storageId}")
    @Operation(summary = "获取文件列表根据文件存储Id")
    public ResponseResult<List<SysFile>> fileList(@PathVariable String storageId) {
        List<SysFile> sysFiles = sysFileService.list(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getStorageId, storageId));
        return ResponseResult.success(sysFiles);
    }

    @Operation(summary = "文件新增")
    @PostMapping("saveFile")
    public ResponseResult<String> saveFile(SysFileDTO sysFileDTO) {
        return ResponseResult.success(sysFileService.saveFile(sysFileDTO));
    }


    @PostMapping("deleteFile")
    @Operation(summary = "删除文件")
    public ResponseResult deleteFile(@RequestBody SysFileDelMoveDTO sysFileDelDTO) {
        sysFileService.deleteFile(sysFileDelDTO);
        return ResponseResult.success();
    }

    @PostMapping("updateFile")
    @Operation(summary = "修改文件")
    public ResponseResult<Boolean> updateFile(@RequestBody SysFile sysFile) {
        return ResponseResult.success(sysFileService.updateFile(sysFile));
    }

    @GetMapping("downFile/{fileId}")
    @Operation(summary = "文件下载")
    public void downFile(@PathVariable String fileId, HttpServletResponse response) {
        SysFile sysFile = sysFileService.getOne(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getFileId, fileId));
        String storageAbsoluteDirectory = fileStorageService.getById(sysFile.getStorageId()).getStorageAbsoluteDirectory();
        String fileFullName = sysFile.getFileFullName();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileFullName);
        String storageDirectory = storageAbsoluteDirectory + fileFullName;
        try (OutputStream out = response.getOutputStream(); InputStream objectResponse = minioTemplate.getResponse(storageDirectory)) {
            objectResponse.transferTo(out);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件下载失败", e);
        }
    }

    @GetMapping("picFileView/{fileId}")
    @Operation(summary = "图片文件查看")
    public ResponseResult<String> picFileView(@PathVariable String fileId) {
        SysFile sysFile = sysFileService.getById(fileId);
        String fileType = sysFile.getFileType();
        String pattern = "^(jpeg|png|gif|jpg)$";
        if (fileType.matches(pattern)) {
            return ResponseResult.success(sysFile.getFileFullPath());
        }
        return ResponseResult.success("不是图片,不允许查看", null);
    }


    @GetMapping("getAllFolders")
    @Operation(summary = "获取所有的文件夹")
    public ResponseResult<List<Tree<String>>> getAllFolders() {
        List<SysFileStorage> list = fileStorageService.list();
        List<Tree<String>> trees = TreeUtil.build(list, "-1", (sysFileStorage, treeNode) -> {
            treeNode.setName(sysFileStorage.getStorageName());
            treeNode.setParentId(sysFileStorage.getStorageParentId());
            treeNode.setId(sysFileStorage.getStorageId());
        });
        return ResponseResult.success(trees);
    }

    @Operation(summary = "文件移动")
    @PostMapping("moveFile")
    public ResponseResult moveFile(@RequestBody SysFileDelMoveDTO sysFileMoveDTO) {
        return sysFileService.moveFile(sysFileMoveDTO);
    }


}
